package com.wz.token;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.Verification;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class TokenContext {

    TokenProperties properties;

    public TokenContext(TokenProperties tokenProperties) {
        this.properties = tokenProperties;
    }

    public TokenContext() {
    }

    /**
     * 生成token字符串
     *
     * @param map 包含用户信息  用于生成token
     * @return token字符串
     */
    public String generateToken(Map map) {
        return JWT.create()
                .withHeader(getHeader())
                .withPayload(getPayload(map))
                .withExpiresAt(getExpireDate())
                .sign(getAlgorithm());
    }

    /**
     * 验证token
     *
     * @param token
     * @return 1验证成功  2 验证失败
     */
    public int validateToken(String token) {
        Verification verification = JWT.require(getAlgorithm());
        JWTVerifier verifier = verification.build();
        //验证
        DecodedJWT decodedJWT = null;
        try {
            decodedJWT = verifier.verify(token);
        } catch (Exception e) {
            String msg = e.toString();
            if (msg.contains("The Token has expired")) {
                //token过期
                return 3;
            }
            return 2;
        }
        //验证成功
        return 1;
    }

    /**
     * 刷新token  有效时间延长 配置的时间
     *
     * @param token
     * @return
     */
    public String refreshToken(String token) {
        //验证token
        int rs = validateToken(token);
        if (rs == 2)
            return null;
        //验证成功
        DecodedJWT decodedJWT = JWT.decode(token);
        Map papload = decodedJWT.getClaims();
        return JWT.create()
                .withHeader(getHeader())
                .withPayload(papload)
                .withExpiresAt(getExpireDate())
                .sign(getAlgorithm());
    }

    /**
     * 解析token字符串  获取公共声明（用户信息）
     *
     * @param token
     * @return
     */
    public Map parseToken(String token) {
        //验证token
        int rs = validateToken(token);
        if (rs != 1)
            return null;
        //验证成功
        DecodedJWT decodedJWT = JWT.decode(token);
        return decodedJWT.getClaims();
    }

    /**
     * jwt头部
     *
     * @return
     */
    Map getHeader() {
        Map map = new HashMap();
        map.put("typ", "JWT");
        map.put("alg", "HMAC256");
        return map;
    }

    /**
     * 获取token 载荷
     *
     * @param map
     * @return
     */
    Map getPayload(Map map) {
        //标准中注册的声明
        Map load = new HashMap();
        load.put("iss", properties.getIss());
        load.put("sub", properties.getSub());
        //公共声明
        if (null != map) {
            load.putAll(map);
        }
        return load;
    }

    /**
     * 获取token过期时间
     *
     * @return
     */
    Date getExpireDate() {
        long expire = properties.getValidateTime();
        if (expire == 0) {
            expire = 60 * 60 * 1000;  //默认有效时间
        }
        long now = System.currentTimeMillis();
        //过期时间
        expire += now;
        return new Date(expire);
    }

    /**
     * 加密算法
     *
     * @return
     */
    Algorithm getAlgorithm() {
        return Algorithm.HMAC256(properties.getSecret());
    }
}